
import com.alibaba.fastjson.JSON
import com.alibaba.fastjson.JSONObject;
import com.binguo.api.controller.OrderController;
import com.binguo.api.response.api.BaseChargeResp;
import com.binguo.api.response.api.BaseUserInfo;
import com.binguo.api.schedule.DataLoadService;
import com.binguo.api.service.ApiOrderService;
import com.binguo.api.service.api.ShopApiInterface;
import com.binguo.common.enums.PayStatus;
import com.binguo.common.enums.PayType;
import com.binguo.common.exception.ServiceException;
import com.binguo.common.util.EncryptUtils;
import com.binguo.common.util.JsonUtil;
import com.binguo.common.util.LoggerUtil
import com.binguo.common.util.PriceUtil;
import com.binguo.common.util.UrlUtils;
import com.binguo.model.api.dto.OrderDTO;
import com.binguo.model.api.dto.OrderItemDTO;
import com.binguo.model.api.vo.OrderVO
import com.binguo.model.model.NormalConfig;
import com.binguo.model.model.OrderItem
import com.binguo.model.model.PayCard;
import com.binguo.model.model.Product;
import com.binguo.model.model.Shop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.*;
import java.util.stream.Collectors;

import static com.binguo.common.util.YPConstants.MD5;

public class MankeBaoService implements ShopApiInterface {
    private static Logger logger = LoggerFactory.getLogger(MankeBaoService.class);

    @Resource
    ApiOrderService apiOrderService;

    @Override
    public BaseChargeResp payPreHandler(OrderDTO orderDTO) {
        try {
            logger.info("进入满客宝订单推送");

            DetailForm [] detailForms = new DetailForm[orderDTO.getItems().size()];
            int i=0;
            for (OrderItemDTO item : orderDTO.getItems()) {
                DetailForm detailForm = new DetailForm();
                Product product = DataLoadService.productMap.get(item.getProductId());
                detailForm.setItemCode(product.getSearchcode().toLowerCase());
                detailForm.setCount(String.valueOf(item.getQuantity()));

                detailForms[i++] = detailForm;
            }
            String host = DataLoadService.mankebaoConfigMap.get(orderDTO.getShopId());
            Integer branchId =
                    DataLoadService.cashierDeskBranchMap.get(orderDTO.getCashierDeskId());

            String deviceId = DataLoadService.cashierDeskDeviceIdMap.get(orderDTO.getCashierDeskId());

            String cardNo = "";
            if (orderDTO.getPayType().getCode().intValue() == PayType.FACEPAY.getCode().intValue()) {
                cardNo = "mkb_" + orderDTO.getCustomerPhone();
            }
            else if (orderDTO.getPayType().getCode().intValue() == PayType.CARDPAY.getCode().intValue()) {
                cardNo = orderDTO.getCardNo();
            }
            else if (orderDTO.getPayType().getCode().intValue() == PayType.MICROPAY.getCode().intValue()) {
                cardNo = orderDTO.getAuthCode();
            }
            else{
                //除以上三种其他的统一用mkb_+用户手机号
                cardNo = "mkb_" + orderDTO.getCustomerPhone();
            }
            ManKeBaoOrderForm orderForm = new ManKeBaoOrderForm(cardNo,
                    deviceId,String.valueOf(branchId),orderDTO.getOrderNo(),
                    "false",null,String.valueOf(System.currentTimeMillis()),
                    orderDTO.getCustomerName(),orderDTO.getCustomerPhone(),orderDTO.getCustomerPhone(),detailForms);

            Shop shop = DataLoadService.shopMap.get(orderDTO.getShopId());
            String method = "api.pay.order.settlement.create";
            String key = getManKeBaoKey(shop.getAppId(),host);
            //签名流程
            TreeMap<String, String> treeMap = new TreeMap<>();
            treeMap.put("method", method);
            treeMap.put("supplierCode", shop.getPhone());
            treeMap.put("requestId", String.valueOf(System.currentTimeMillis()));
            treeMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
            treeMap.put("version", "1.0");
            treeMap.put("data", JSON.toJSONString(orderForm));
            String content = JSON.toJSONString(treeMap);
            String sign = manKeBaosign(content,key);
            logger.info("满客宝签名:"+sign);
            if(sign.equals("")){
                throw new ServiceException("满客宝key获取失败");
            }
            treeMap.put("sign",sign);
            System.out.println("请求参数：" + JSON.toJSONString(treeMap));
            System.out.println("请求明文：" + content);
            Map map = UrlUtils.send3(host + "/open/api",treeMap,"utf-8");
            logger.info("mankebao result ={}", JsonUtil.toJson(map));
            System.out.println("返回参数：" + JsonUtil.toJson(map));

            if(String.valueOf(map.get("code")).equals("10000")){
                BaseChargeResp<OrderVO> result = new BaseChargeResp<>();

                OrderVO orderVO = apiOrderService._createOrder(orderDTO, PayStatus.SUCCESS);

                try{

                    if (StringUtils.hasText(map.get("data"))) {

                        String temp = map.get("data");
                        System.out.println("temp map===" + temp);

                        JSONObject jsonObjectData = JSONObject.parseObject(temp);
                        Map<String,Object> dataMap = (Map<String,Object>)jsonObjectData;//
                        String balanceStr = dataMap.get("balance");
                        System.out.println("balanceStr===" + balanceStr);

                        PayCard pc = new PayCard();
                        if (orderVO.getPayCard() != null) {
                            BeanUtils.copyProperties(orderVO.getPayCard(), pc)
                        }
                        pc.setAccountbalance(PriceUtil.getRealPrice(balanceStr));
                        orderVO.setPayCard(pc);
                    }
                }catch (Exception e){

                }

                result.setData(orderVO);
                result.setCode(200);
                return result;
            }else{
                throw new ServiceException("支付失败");
            }

        } catch (Exception e) {
            throw new ServiceException(e.getMessage());
        }

    }

    @Override
    public BaseChargeResp payPostHandler(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseUserInfo getUserInfo(String cardNo) {
        return null;
    }

    @Override
    public BaseChargeResp getProductList() {
        return null;
    }

    @Override
    public BaseChargeResp cardPay(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseChargeResp wxPay(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseChargeResp aliPay(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseChargeResp facePay(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseChargeResp cashPay(OrderDTO orderDTO) {
        return null;
    }

    @Override
    public BaseChargeResp qrCodePay(OrderDTO orderDTO) {
        return null;
    }

    //签名
    public String manKeBaosign(String data, String key) throws Exception {
        logger.info(" 参与生成满客宝MD5签名key:"+key);
        logger.info(" 参与生成满客宝MD5签名参数:"+data);
        //得到明文的字节数组
        byte[] btInput = (data + key).getBytes();
        // 创建一个提供信息摘要算法的对象(MD5摘要算法)
        MessageDigest messageDigest = MessageDigest.getInstance(MD5);
        // 使用指定的字节更新摘要
        messageDigest.update(btInput);
        return String.format("%032x", new BigInteger(1, messageDigest.digest()));
    }

    public String getManKeBaoKey(String appid,String host) throws Exception{
//        return "fcb65648cb8d454d9a15b888538b248d";
        TreeMap<String, String> treeMap = new TreeMap<>();
        treeMap.put("supplierCode", "400140");
        treeMap.put("keyType", "2");
        treeMap.put("source", "YUN_PENG");
        String url = host + "/report/api/v1/open/supplier/gerSupplierSecretKey";
        String key = getKeyByAppID(appid);
        String sign = generateSign(treeMap,key);
        treeMap.put("sign",sign);

        Map map = UrlUtils.send3(url,treeMap,"utf-8");
        if(map.get("code").equals(200) && !StringUtils.isEmpty(map.get("md5Key"))){
            return map.get("md5Key").toString();
        }else{
            return null;
        }
    }

    public static String generateSign(Map<String, String> param, String appKey) {
        StringBuilder sb = new StringBuilder();

        for (Map.Entry<String,String> en : param.entrySet()) {
            sb.append(en.getKey()).append("=").append(en.getValue()).append("&");
        }
        sb.append("key=").append(appKey);

        String sign = EncryptUtils.md5(sb.toString()).toUpperCase();
        return sign;
    }

    public String getKeyByAppID(String appId){
        Shop shop = DataLoadService.shopAppIdMap.get(appId);

        if (shop != null && (shop.getStatus() == 0 || shop.getStatus() == 3)) {
            LoggerUtil.console.info("shop info:{}", shop.getName());
            return shop.getSecurityKey();
        } else {
            throw new ServiceException("商户状态异常");
        }
    }
}


class DetailForm {

    private String itemCode;

    private String count;

    public String getItemCode() {
        return itemCode;
    }

    public void setItemCode(String itemCode) {
        this.itemCode = itemCode;
    }

    public String getCount() {
        return count;
    }

    public void setCount(String count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "DetailForm{" +
                "itemCode='" + itemCode + '\'' +
                ", count='" + count + '\'' +
                '}';
    }
}

class ManKeBaoOrderForm {
    /**
     * cardNo	string	50	是	饭卡号、付款码、用户二维码(mkb-)、本地刷脸用户ID(mkb_)、在线刷脸fToken(user_)
     */
    private String cardNo;
    /**
     * deviceCode	string	50	是	设备SN
     */
    private String deviceCode;
    /**
     * branchId	string	50	是	第三方门店ID,不传设备SN时必填
     */
    private String branchId;
    /**
     * deviceOrderId	String	20	是	设备订单ID(刷脸时由机头生成，刷卡或扫码时由结算台生成)
     */
    private String deviceOrderId;
    /**
     * offlineType	string	20	是	离线模式类型(true:离线、false:在线)
     */
    private String offlineTyoe;
    /**
     * payMoney	string	20	否	不传菜肴时必填支付金额
     */
    private String payMoney;
    /**
     * orderCreateTime	string	20	否	(离线模式必填)终端下单时间
     */
    private String orderCreateTime;
    /**
     * userName	string	20	否	(离线模式必填)用户姓名
     */
    private String userName;
    /**
     * mobile	string	20	否	(离线模式必填)手机号
     */
    private String mobile;
    /**
     * faceLinkmanMobile	string	20	否	(离线模式必填)紧急联系人手机号
     */
    private String faceLinkmanMobile;
    /**
     * details	string	-	否	菜肴信息(数组格式)
     * details[0].itemCode	string	20	是	菜品编号
     * details[0].count	string	20	是	菜品数量
     */
    private DetailForm[] details;

    public String getCardNo() {
        return cardNo;
    }

    public void setCardNo(String cardNo) {
        this.cardNo = cardNo;
    }

    public String getDeviceCode() {
        return deviceCode;
    }

    public void setDeviceCode(String deviceCode) {
        this.deviceCode = deviceCode;
    }

    public String getBranchId() {
        return branchId;
    }

    public void setBranchId(String branchId) {
        this.branchId = branchId;
    }

    public String getDeviceOrderId() {
        return deviceOrderId;
    }

    public void setDeviceOrderId(String deviceOrderId) {
        this.deviceOrderId = deviceOrderId;
    }

    public String getOfflineTyoe() {
        return offlineTyoe;
    }

    public void setOfflineTyoe(String offlineTyoe) {
        this.offlineTyoe = offlineTyoe;
    }

    public String getPayMoney() {
        return payMoney;
    }

    public void setPayMoney(String payMoney) {
        this.payMoney = payMoney;
    }

    public String getOrderCreateTime() {
        return orderCreateTime;
    }

    public void setOrderCreateTime(String orderCreateTime) {
        this.orderCreateTime = orderCreateTime;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getFaceLinkmanMobile() {
        return faceLinkmanMobile;
    }

    public void setFaceLinkmanMobile(String faceLinkmanMobile) {
        this.faceLinkmanMobile = faceLinkmanMobile;
    }

    public DetailForm[] getDetails() {
        return details;
    }

    public void setDetails(DetailForm[] details) {
        this.details = details;
    }

    public ManKeBaoOrderForm(){}

    @Override
    public String toString() {
        return "ManKeBaoOrderForm{" +
                "cardNo='" + cardNo + '\'' +
                ", deviceCode='" + deviceCode + '\'' +
                ", branchId='" + branchId + '\'' +
                ", deviceOrderId='" + deviceOrderId + '\'' +
                ", offlineTyoe='" + offlineTyoe + '\'' +
                ", payMoney='" + payMoney + '\'' +
                ", orderCreateTime='" + orderCreateTime + '\'' +
                ", userName='" + userName + '\'' +
                ", mobile='" + mobile + '\'' +
                ", faceLinkmanMobile='" + faceLinkmanMobile + '\'' +
                ", details=" + Arrays.toString(details) +
                '}';
    }

    public ManKeBaoOrderForm(String cardNo, String deviceCode, String branchId, String deviceOrderId, String offlineTyoe, String payMoney, String orderCreateTime, String userName, String mobile, String faceLinkmanMobile, DetailForm[]  details) {
        if(null != cardNo){
            this.cardNo = cardNo;
        }
        if(null != deviceCode){
            this.deviceCode = deviceCode;
        }
        if(null != branchId){
            this.branchId = branchId;
        }
        if(null != deviceOrderId){
            this.deviceOrderId = deviceOrderId;
        }
        if(null != offlineTyoe){
            this.offlineTyoe = offlineTyoe;
        }
        if(null != payMoney){
            this.payMoney = payMoney;
        }
        if(null != orderCreateTime){
            this.orderCreateTime = orderCreateTime;
        }
        if(null != userName){
            this.userName = userName;
        }
        if(null != mobile){
            this.mobile = mobile;
        }
        if(null != faceLinkmanMobile){
            this.faceLinkmanMobile = faceLinkmanMobile;
        }
        if(null != details){
            this.details = details;
        }
    }
}